﻿//using Stee.CAP8.MessageBus.Sagas.Core.HanlderInvokers;
//using Stee.CAP8.MessageBus.Sagas.Core.Steps;
//using Stee.CAP8.MessageBus.Sagas.Core.SubscribeStores;
//using Stee.CAP8.MessageBus.Sagas.Core.Transactions;
//using Stee.CAP8.MessageBus.Sagas.Messages.Messages;
//using System;
//using System.Collections.Concurrent;
//using System.Collections.Generic;
//using System.Linq;
//using System.Reflection;
//using System.Text;
//using System.Threading.Tasks;

//namespace Stee.CAP8.MessageBus.Sagas.Core.Pipeline.Reiceve
//{
//    public class SagaHandlersStep 
//    {
//        readonly ISubscribeStore _subscribeStore;
//        readonly ConcurrentDictionary<Type, MethodInfo> _dispatchMethods = new ConcurrentDictionary<Type, MethodInfo>();

//        public SagaHandlersStep(ISubscribeStore subscribeStore)
//        {
//            _subscribeStore = subscribeStore ?? throw new ArgumentNullException(nameof(subscribeStore));
//        }

//        public async Task Process<TMessage>(IncomingStepContext context, Func<Task> next)
//        {
//            var transactionContext = context.Load<ITransactionContext>(); 
//            var message = context.Load<Message>();
//            var body = message.Body;
//            var messageType = body.GetType();
//            var methodToInvoke = _dispatchMethods
//                .GetOrAdd(messageType, type => GetDispatchMethod(messageType));
//            int handlersInvoked = 0;
//            var handlerInvokers = await((Task<HandlerInvokers>)methodToInvoke.Invoke(this, new[] { body, transactionContext, message }));
//            for (int index = 0; index < handlerInvokers.Count(); index++)
//            {
//                var invoker = handlerInvokers[index];

//                await invoker.Invoke();
//                handlersInvoked++;
//            }
//            await next();


//        }
//        async Task<HandlerInvokers> GetHandlerInvokers<TMessage>(TMessage message, ITransactionContext transactionContext, Message logicalMessage)
//        {
//            var handlers =  _subscribeStore.GetMessageHandlersForMessage<TMessage>();

//            var listOfHandlerInvokers = handlers
//                .Select(handler => CreateHandlerInvoker(handler, message, transactionContext, logicalMessage))
//                .ToList();

//            return new HandlerInvokers(logicalMessage, listOfHandlerInvokers);
//        }

//        /// <summary>
//        /// Creates instance of HandlerInvoker
//        /// </summary>
//        protected virtual HandlerInvoker CreateHandlerInvoker<TMessage>(IHandleMessages<TMessage> handler, TMessage message, ITransactionContext transactionContext, Message logicalMessage)
//        {
//            return new HandlerInvoker<TMessage>(() => handler.Handle(message), handler, transactionContext);
//        }

//        MethodInfo GetDispatchMethod(Type messageType)
//        {
//            const string methodName = nameof(GetHandlerInvokers);

//            var genericDispatchMethod = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance)
//                ?? throw new ArgumentException($"Could not find the {methodName} method?!");

//            return genericDispatchMethod.MakeGenericMethod(messageType);
//        }
//    }
//}
